<template>
  <div class="image-gallery-component">
    <!-- 图片展示区域 -->
    <div v-if="imageList.length > 0" class="image-gallery">
      <div class="image-container">
        <!-- 图片列表 -->
        <el-image
          v-for="(image, index) in displayImages"
          :key="`${uniqueKey}-${image.id || index}-${index}`"
          :src="image.url || image.fileUrl"
          class="gallery-image"
          :fit="fit"
          :preview-src-list="previewList"
          :initial-index="index"
          :preview-teleported="true"
          :hide-on-click-modal="false"
          :lazy="lazy"
          @click="handleImageClick(image, index)"
        >
          <!-- 加载失败显示 -->
          <template #error>
            <div class="image-error">
              <el-icon><Picture /></el-icon>
              <span>{{ errorText }}</span>
            </div>
          </template>
          
          <!-- 加载中显示 -->
          <template #placeholder>
            <div class="image-loading">
              <el-icon class="is-loading"><Loading /></el-icon>
              <span>加载中...</span>
            </div>
          </template>
        </el-image>
        
        <!-- 更多图片提示 -->
        <div 
          v-if="shouldShowMoreIndicator" 
          class="image-more"
          @click="handleMoreClick"
        >
          <span>+{{ imageList.length - maxDisplayCount }}</span>
        </div>
      </div>
      
      <!-- 图片信息 -->
      <div v-if="showInfo" class="image-info">
        <span class="image-count">共 {{ imageList.length }} 张图片</span>
        <span class="image-tip">{{ tipText }}</span>
      </div>
    </div>
    
    <!-- 无数据提示 -->
    <div v-else class="no-data">
      <el-icon><Picture /></el-icon>
      <span>{{ noDataText }}</span>
    </div>
  </div>
</template>

<script setup lang="ts">
import { computed, ref } from 'vue'
import { Picture, Loading } from '@element-plus/icons-vue'

// 图片信息接口
export interface ImageInfo {
  id?: string | number
  url?: string
  fileUrl?: string
  fileName?: string
  fileSize?: number
  [key: string]: any
}

// 组件属性
interface Props {
  /** 图片列表 */
  images?: ImageInfo[]
  /** 最大显示数量 */
  maxDisplayCount?: number
  /** 图片适应方式 */
  fit?: 'fill' | 'contain' | 'cover' | 'none' | 'scale-down'
  /** 是否懒加载 */
  lazy?: boolean
  /** 是否显示更多提示 */
  showMoreIndicator?: boolean
  /** 是否显示图片信息 */
  showInfo?: boolean
  /** 错误提示文本 */
  errorText?: string
  /** 无数据提示文本 */
  noDataText?: string
  /** 提示文本 */
  tipText?: string
  /** 唯一标识符 */
  uniqueKey?: string
  /** 是否禁用 */
  disabled?: boolean
}

// 默认属性值
const props = withDefaults(defineProps<Props>(), {
  images: () => [],
  maxDisplayCount: 3,
  fit: 'cover',
  lazy: true,
  showMoreIndicator: true,
  showInfo: true,
  errorText: '加载失败',
  noDataText: '暂无图片',
  tipText: '点击图片可预览大图',
  uniqueKey: 'image-gallery',
  disabled: false
})

// 事件定义
const emit = defineEmits<{
  /** 图片点击事件 */
  'image-click': [image: ImageInfo, index: number]
  /** 更多图片点击事件 */
  'more-click': [images: ImageInfo[]]
  /** 预览事件 */
  'preview': [image: ImageInfo, index: number]
}>()

// 响应式数据
const currentIndex = ref(0)

// 计算属性
const imageList = computed(() => {
  if (!props.images || !Array.isArray(props.images)) {
    return []
  }
  return props.images.filter(image => image && (image.url || image.fileUrl))
})

const displayImages = computed(() => {
  // 只显示实际存在的图片，不显示占位符
  return imageList.value
})

const previewList = computed(() => {
  return imageList.value.map(image => image.url || image.fileUrl).filter(Boolean)
})

// 是否显示更多提示
const shouldShowMoreIndicator = computed(() => {
  return props.showMoreIndicator && imageList.value.length > props.maxDisplayCount
})

// 方法定义
const handleImageClick = (image: ImageInfo, index: number) => {
  if (props.disabled) return
  
  emit('image-click', image, index)
  emit('preview', image, index)
}

const handleMoreClick = () => {
  if (props.disabled) return
  
  emit('more-click', imageList.value)
}

// 暴露方法给父组件
defineExpose({
  /** 获取图片列表 */
  getImageList: () => imageList.value,
  /** 获取预览列表 */
  getPreviewList: () => previewList.value,
  /** 获取当前索引 */
  getCurrentIndex: () => currentIndex.value,
  /** 设置当前索引 */
  setCurrentIndex: (index: number) => {
    currentIndex.value = index
  }
})
</script>

<style lang="scss" scoped>
.image-gallery-component {
  width: 100%;
  
  .image-gallery {
    .image-container {
      display: flex;
      flex-wrap: wrap;
      gap: 8px;
      margin-bottom: 8px;
      position: relative;

      .gallery-image {
        width: 80px;
        height: 80px;
        border-radius: 8px;
        border: 1px solid #e4e7ed;
        cursor: pointer;
        transition: all 0.3s ease;
        overflow: hidden;

        &:hover {
          transform: scale(1.05);
          box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
        }

        &:active {
          transform: scale(0.98);
        }
      }

      .image-more {
        width: 80px;
        height: 80px;
        background: rgba(0, 0, 0, 0.6);
        color: white;
        display: flex;
        align-items: center;
        justify-content: center;
        border-radius: 8px;
        font-size: 14px;
        font-weight: 500;
        cursor: pointer;
        transition: all 0.3s ease;

        &:hover {
          background: rgba(0, 0, 0, 0.8);
          transform: scale(1.05);
        }

        &:active {
          transform: scale(0.98);
        }
      }

      .image-error {
        width: 100%;
        height: 100%;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        background: #f5f7fa;
        color: #909399;
        font-size: 12px;

        .el-icon {
          font-size: 20px;
          margin-bottom: 4px;
        }
      }

      .image-loading {
        width: 100%;
        height: 100%;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        background: #f5f7fa;
        color: #909399;
        font-size: 12px;

        .el-icon {
          font-size: 20px;
          margin-bottom: 4px;
        }
      }
    }

    .image-info {
      display: flex;
      justify-content: space-between;
      align-items: center;
      font-size: 12px;
      color: #909399;

      .image-count {
        font-weight: 500;
      }

      .image-tip {
        color: #409eff;
        cursor: pointer;

        &:hover {
          text-decoration: underline;
        }
      }
    }
  }

  .no-data {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 40px 20px;
    color: #c0c4cc;
    font-style: italic;
    background: #f5f7fa;
    border-radius: 8px;
    border: 1px dashed #d9d9d9;

    .el-icon {
      font-size: 32px;
      margin-bottom: 8px;
      color: #d9d9d9;
    }
  }

  // 禁用状态
  &.disabled {
    .gallery-image,
    .image-more {
      cursor: not-allowed;
      opacity: 0.6;

      &:hover {
        transform: none;
        box-shadow: none;
      }
    }

    .image-tip {
      cursor: not-allowed;
      color: #c0c4cc;

      &:hover {
        text-decoration: none;
      }
    }
  }

  // 响应式设计
  @media (max-width: 768px) {
    .image-gallery {
      .image-container {
        gap: 6px;

        .gallery-image,
        .image-more {
          width: 60px;
          height: 60px;
        }
      }

      .image-info {
        font-size: 11px;
      }
    }
  }

  @media (max-width: 480px) {
    .image-gallery {
      .image-container {
        gap: 4px;

        .gallery-image,
        .image-more {
          width: 50px;
          height: 50px;
        }
      }
    }
  }
}
</style>
